/*
 * Copyright the original author or authors.
 * 
 * Licensed under the MOZILLA PUBLIC LICENSE, Version 1.1 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *	  http://www.mozilla.org/MPL/MPL-1.1.html
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.googlecode.milib.display {
	import com.googlecode.milib.base.MLBaseClass;
	import com.googlecode.milib.vo.Scale9VO;

	import flash.display.BitmapData;
	import flash.display.MovieClip;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;

	/**
	 * @author Marek Brun
	 */
	public class Scale9BitmapData extends MLBaseClass {
		
		private var slice9Bitmaps:Array;		
		private var scale9:Scale9VO;		
		private var baseWidths:Array;		
		private var baseHeights:Array;
		private var baseWidth:int;
		private var baseHeight:int;		

		public function Scale9BitmapData(baseBD:BitmapData, scale9:Scale9VO=null) {
			//var scaledBD:BitmapData=new BitmapData(width, height, true, 0x00FF00);
			if(scale9==null){ this.scale9=new Scale9VO(); }
			else{ this.scale9=scale9; }
			
			baseWidth=baseBD.width;			baseHeight=baseBD.height;
			
			//cutting bitmap for 9 base bitmaps 
			baseWidths=[
				baseBD.width*this.scale9.xLeft, //left				baseBD.width-baseBD.width*(this.scale9.xLeft+1-this.scale9.xRight), //mid
				baseBD.width*(1-this.scale9.xRight) //right
			];
			baseHeights=[
				baseBD.height*this.scale9.yUp, //up
				baseBD.height-baseBD.height*(this.scale9.yUp+1-this.scale9.yDown), //mid
				baseBD.height*(1-this.scale9.yDown) //down
			];
			var xs:Array=[0, baseWidths[0], baseWidths[0]+baseWidths[1]];
			var ys:Array=[0, baseHeights[0], baseHeights[0]+baseHeights[1]];
			
			
			slice9Bitmaps=[[], [], []];
			
			var ix:uint, iy:uint, fragmentBD:BitmapData;
			for(ix=0;ix<3;ix++){
				for(iy=0;iy<3;iy++){
					fragmentBD=new BitmapData(baseWidths[ix], baseHeights[iy], true, 0x00000000);
					fragmentBD.copyPixels(baseBD, new Rectangle(xs[ix], ys[iy], baseWidths[ix], baseHeights[iy]), new Point(0, 0));
					slice9Bitmaps[ix][iy]=fragmentBD;
				}
			}
			
		}
		
		public function getMinWidthWithoutSmashing():Number {
			return baseWidths[0]+baseWidths[2]; 
		}
		
		public function getMinHeightWithoutSmashing():Number {
			return baseHeights[0]+baseHeights[2];
		}
		
		public function getScaled9BitmapData(width:Number, height:Number):BitmapData {
			if(width<1){ width=1; }
			if(height<1){ height=1; }
			var scaledBD:BitmapData=new BitmapData(width, height, true, 0x00000000);
			
			var tsmX:TwoSidesAndMidSmashableModel=new TwoSidesAndMidSmashableModel();
			tsmX.setupSide0Length=baseWidths[0];
			tsmX.setupSide1Length=baseWidths[2];
			tsmX.setupLength=width;
			
			var tsmY:TwoSidesAndMidSmashableModel=new TwoSidesAndMidSmashableModel();
			tsmY.setupSide0Length=baseHeights[0];
			tsmY.setupSide1Length=baseHeights[2];
			tsmY.setupLength=height;
			
			var matrix:Matrix=new Matrix();
			matrix.scale(width/baseWidth, height/baseHeight);
			
			//left up
			mergeBitmapWithExactFit(scaledBD, slice9Bitmaps[0][0], 0, 					0, tsmX.getSide0Length(), tsmY.getSide0Length());
			//mid up			mergeBitmapWithExactFit(scaledBD, slice9Bitmaps[1][0], tsmX.getMidIniPos(), 0, tsmX.getMidLength(), tsmY.getSide0Length());
			//right up			mergeBitmapWithExactFit(scaledBD, slice9Bitmaps[2][0], tsmX.getSide1IniPos(), 0, tsmX.getSide1Length(), tsmY.getSide0Length());
			
			//left mid
			mergeBitmapWithExactFit(scaledBD, slice9Bitmaps[0][1], 0, 					tsmY.getMidIniPos(), tsmX.getSide0Length(), tsmY.getMidLength());
			//mid mid
			mergeBitmapWithExactFit(scaledBD, slice9Bitmaps[1][1], tsmX.getMidIniPos(), tsmY.getMidIniPos(), tsmX.getMidLength(), tsmY.getMidLength());
			//right mid
			mergeBitmapWithExactFit(scaledBD, slice9Bitmaps[2][1], tsmX.getSide1IniPos(), tsmY.getMidIniPos(), tsmX.getSide1Length(), tsmY.getMidLength());
			
			//left down
			mergeBitmapWithExactFit(scaledBD, slice9Bitmaps[0][2], 0, 					tsmY.getSide1IniPos(), tsmX.getSide0Length(), tsmY.getSide1Length());
			//mid down
			mergeBitmapWithExactFit(scaledBD, slice9Bitmaps[1][2], tsmX.getMidIniPos(), tsmY.getSide1IniPos(), tsmX.getMidLength(), tsmY.getSide1Length());
			//right down
			mergeBitmapWithExactFit(scaledBD, slice9Bitmaps[2][2], tsmX.getSide1IniPos(), tsmY.getSide1IniPos(), tsmX.getSide1Length(), tsmY.getSide1Length());
			
			return scaledBD;
		}
		
		protected function mergeBitmapWithExactFit(bitmapPasteIn:BitmapData, bitmapToPaste:BitmapData, x:Number, y:Number, width:Number, height:Number):void {
			height=Math.round(height);
			width=Math.round(width);
			if(!width || !height){ return; }
			var matrix:Matrix=new Matrix();
			matrix.scale(width/bitmapToPaste.width, height/bitmapToPaste.height);
			var transformedBitmapToPaste:BitmapData=new BitmapData(width, height, true, 0x00000000);
			transformedBitmapToPaste.draw(bitmapToPaste, matrix, null, null, new Rectangle(0, 0, width, height), false);
			
			bitmapPasteIn.merge(transformedBitmapToPaste, new Rectangle(0, 0, width, height), new Point(Math.round(x), Math.round(y)), 0xFF, 0xFF, 0xFF, 0xFF);
			
			transformedBitmapToPaste.dispose();
		}
		
		public function getBaseWidth():Number {
			return baseWidth;
		}
		
		public function getBaseHeight():Number {
			return baseHeight;
		}
		
		public static function createFromSlicedMC(mc:MovieClip):Scale9BitmapData {
			var bodyBD:BitmapData=new BitmapData(mc.width, mc.height, true, 0x00000000);
			bodyBD.draw(mc);
			
			var scale9:Scale9VO=new Scale9VO(
				mc.scale9Grid.x/mc.width,
				(mc.scale9Grid.x+mc.scale9Grid.width)/mc.width,
				mc.scale9Grid.y/mc.height,
				(mc.scale9Grid.y+mc.scale9Grid.height)/mc.height
			);
			
			return new Scale9BitmapData(bodyBD, scale9);
		}
		
	}
}
